#ifndef __G_SHA_H__
#define __G_SHA_H__

#include "g_1903.h"
#include "g_sysctrl.h"
#include "g_crypt.h"

typedef enum
{
  SHATYPE_1	= 0,
  SHATYPE_224 = 1,
  SHATYPE_256 = 2,
  SHATYPE_384 = 3,
  SHATYPE_512 = 4,
  SHATYPE_SM3 = 5
}SHA_ModeTypeDef;

typedef struct SHA
{
  uint32_t SHA_Data[16];					// 	用来保存SHA_RESULT寄存器的值
  uint8_t  SHA_Digest_Length;			    //	SHA类型加密后的数据长度
  uint8_t  SHA_CBlock;					//	SHA类型数据块大小
  uint32_t SHA_LEN;						//	数据实时长度
  uint8_t  SHA_Mode;						//	SHA模式
  uint8_t  SHA_Ctrl;                      //  数据bit位是否超过1024，控制寄存器用
} SHA_CTX;

#define SHA160_DIGEST_LENGTH	20
#define SHA224_DIGEST_LENGTH	28
#define SHA256_DIGEST_LENGTH	32
#define SHA384_DIGEST_LENGTH	48
#define SHA512_DIGEST_LENGTH	64

#define RET_SHA_INIT_TRUE			1
#define RET_SHA_BUSY        (('R'<<24)|('S'<<16)|('B'<<8)|('U'))  //硬件单元处于忙状态
#define RET_SHA_MODE_ERR    (('R'<<24)|('S'<<16)|('M'<<8)|('E'))  //输入计算类型错误
#define RET_SHA_SUCCESS     (('R'<<24)|('S'<<16)|('S'<<8)|('U'))  //计算成功
#define RET_SHA_ERROR		(('R'<<24)|('S'<<16)|('S'<<8)|('E'))  //SHA错误


#define SHA_DIGEST_LENGTH 		20 		//160
#define SHA224_DIGEST_LENGTH	28		//224
#define SHA256_DIGEST_LENGTH	32		//256

#define SHA384_DIGEST_LENGTH	48		//384
#define SHA512_DIGEST_LENGTH	64		//512

/**
  * @method	sha
  * @brief	Secure Hash Alogrithm
  * @param	mode   : SHA mode: SHA_1/SHA_224/SHA_256/SHA_384/SHA_512
  * @param	SHA_CTX *c : SHA struct
  * @retval RET_SHA_MODE_ERR or RET_SHA_INIT_TRUE
  */
uint32_t SHA_Init(SHA_CTX *c,SHA_ModeTypeDef mode);
/**
  * @method	sha
  * @brief	updata Hash Alogrithm
  * @param	SHA_CTX *c : SHA struct
  * @param	input  : input data buffer
  * @param	ibytes : size of input data
  * @retval RET_SHA_SUCCESS or RET_SHA_ERROR
  */
uint32_t SHA_Update(SHA_CTX *c,uint8_t *input,uint32_t ibytes);
/**
  * @method	sha
  * @brief	output sha results
  * @param	SHA_CTX *c : SHA struct
  * @param	output : output data buffer
  * @retval RET_SHA_SUCCESS
  */
uint32_t SHA_Final(SHA_CTX *c,uint8_t *output);


/**
  * @method	sha
  * @brief	Secure Hash Alogrithm
  * @param	mode   : SHA mode: SHA_1/SHA_224/SHA_256/SHA_384/SHA_512
  * @param	output : output data buffer
  * @param	input  : input data buffer
  * @param	ibytes : size of input data
  * @retval SHA_TYPE_ERR or SHA_CRYPT_BUSY
  */
uint32_t SHA(SHA_ModeTypeDef mode, uint8_t *output, uint8_t *input,uint32_t ibytes);

/**
  * @method	sha_sec
  * @brief	Secure Hash Alogrithm Rand Copy
  * @param	mode   : SHA mode: SHA_256/SHA_384/SHA_512
  * @param	output : output data buffer
  * @param	input  : input data buffer
  * @param	ibytes : size of input data
  * @param	f_rng  : true random number generation function point
  * @param	p_rng  : true random number generation para
  * @retval SHA_TYPE_ERR or SHA_CRYPT_BUSY
  */
uint32_t SHA_Sec(SHA_ModeTypeDef mode,  uint8_t *output, uint8_t *input,uint32_t ibytes,
               rng_callback f_rng, void *p_rng);

/**
  * @method	sha
  * @brief	Secure Hash Alogrithm
  * @param	mode		:SHA mode: SHA_1/SHA_224/SHA_256/SHA_384/SHA_512
  * @param	input		:input data buffer
  * @param	ibytes		:size of input data
  * @retval 			:SHA_TYPE_ERR or SHA_CRYPT_BUSY
  */
uint32_t sha_first(SHA_ModeTypeDef mode,uint8_t *output,uint8_t *input,uint32_t ibytes);

/**
  * @method	sha
  * @brief	Secure Hash Alogrithm
  * @param	mode		:SHA mode: SHA_1/SHA_224/SHA_256/SHA_384/SHA_512
  * @param	input		:input data buffer
  * @param	ibytes		:size of input data
  * @retval 			:SHA_TYPE_ERR or SHA_CRYPT_BUSY
  */
uint32_t sha_mid(SHA_ModeTypeDef mode,uint8_t *output,uint8_t *input,uint32_t ibytes);

/**
  * @method	sha
  * @brief	Secure Hash Alogrithm
  * @param	mode		:SHA mode: SHA_1/SHA_224/SHA_256/SHA_384/SHA_512
  * @param	output		:output data buffer
  * @param	input		:input data buffer
  * @param	ibytes		:size of input data
  * @retval 			:SHA_TYPE_ERR or SHA_CRYPT_BUSY
  */
uint32_t sha_last(SHA_ModeTypeDef mode,uint8_t *output,uint8_t *input,uint32_t ibytes);


/**
  * @method	SHA_Enhance
  * @brief	Secure Hash Alogrithm
  * @param	mode		:SHA mode: SHA_1/SHA_224/SHA_256/SHA_384/SHA_512
  * @param	output		:output data buffer
  * @param	input		:input data buffer
  * @param	ibytes		:size of input data
  * @param     totallen		:size of totallen
  * @param     step               :step = 0 head,  step = 1 middle,  step = 2 tail
  * @retval 			:SHA_TYPE_ERR or SHA_CRYPT_BUSY
  */
uint32_t SHA_Enhance(SHA_ModeTypeDef mode,  uint8_t *output, uint8_t *input,uint32_t ibytes, uint32_t totallen,
              uint8_t step);
#endif

